package com.sfpay.coreplatform.order.service.proxy.account.impl;

import java.net.SocketTimeoutException;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.sfpay.coreplatform.account.service.IAccountInfoQueryService;
import com.sfpay.coreplatform.account.service.ITallySerialService;
import com.sfpay.coreplatform.account.service.ITransferService;
import com.sfpay.coreplatform.account.service.exception.AccountServiceException;
import com.sfpay.coreplatform.account.valueobject.dto.TallySerialQuery;
import com.sfpay.coreplatform.account.valueobject.dto.Transfer;
import com.sfpay.coreplatform.account.valueobject.tmo.AccountVO;
import com.sfpay.coreplatform.account.valueobject.tmo.TallySerial;
import com.sfpay.coreplatform.order.common.OrderResponseCode;
import com.sfpay.coreplatform.order.service.exception.OrderServiceException;
import com.sfpay.coreplatform.order.service.proxy.account.IAccountMgrProxyService;
import com.sfpay.framework.base.pagination.IPage;

@Service
public class AccountMgrProxyServiceImpl implements IAccountMgrProxyService {

	@Resource
	private ITallySerialService tallySerialService;

	@Resource
	IAccountInfoQueryService accountQueryService;

	@Resource
	ITransferService transferService;


	private static Logger logger = LoggerFactory
			.getLogger(AccountMgrProxyServiceImpl.class);

	/**
	 * 方法说明：根据账户编号查找账户信息
	 * 
	 * @param accNo
	 * @return
	 * @throws OrderServiceException
	 */
	public AccountVO findAccountInfoByAccountNo(Long accNo)
			throws OrderServiceException {
		if (logger.isDebugEnabled()) {
			logger.debug("method:findAccountInfoByAccountNo {accNo=" + accNo
					+ "}");
		}
		try {
			return accountQueryService.findAccountInfoByAccountNo(accNo);
		} catch (AccountServiceException se) {
			logger.error("invoke account findAccountInfoByAccountNo ServiceException:",se);
			throw new OrderServiceException(OrderResponseCode.ORDER_RESPONSE_ACC_HANDEL_FAIL, "account service error" + se.getMessage());
		} catch (Exception e) {
			logger.error(
					"invoke account findAccountInfoByAccountNo Exception:", e);
			throw new OrderServiceException(
					OrderResponseCode.HESSIAN_INVOKE_EXCEPTION,
					"findAccountInfoByAccountNo Exception: ", e);
		}
	}

	/**
	 * 方法说明：根据账户编号查找账户信息，适用于小量获取数据。
	 * 
	 * @param accNoList
	 *            账户编号组成的LIST
	 * @return Map<String,AccountVO>: String: 账户编号 AccountVO：账户信息
	 * @throws OrderServiceException
	 */
	public Map<Long, AccountVO> findAccountInfo(List<Long> accNoList)
			throws OrderServiceException {
		try {
			return accountQueryService.findAccountInfo(accNoList);
		} catch (AccountServiceException se) {
			logger.error("invoke account findAccountInfo ServiceException:", se);
			throw new OrderServiceException(OrderResponseCode.ORDER_RESPONSE_ACC_HANDEL_FAIL, "account service error" + se.getMessage());
		} catch (Exception e) {
			logger.error("invoke account findAccountInfo Exception:", e);
			throw new OrderServiceException(
					OrderResponseCode.HESSIAN_INVOKE_EXCEPTION,
					"invoke account findAccountInfo Exception: ", e);
		}
	}

	@Override
	public IPage<TallySerial> queryTallySerial(TallySerialQuery queryData,
			int pageNo, int pageSize) throws OrderServiceException {
		IPage<TallySerial> tallySerials = null;
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("queryTallySerial request is {" 
			     + "queryData=" + queryData
			     + ", pageNo=" + pageNo
			     + ", pageSize=" + pageSize +"}");
			}
			tallySerials = tallySerialService.findTallySerialByPage(queryData,
					pageNo, pageSize);
		} catch (AccountServiceException se) {
			logger.error(
					"invoke account findTallySerialByPage page ServiceException:",
					se);
			throw new OrderServiceException(OrderResponseCode.ORDER_RESPONSE_ACC_HANDEL_FAIL, se.getMessage());
		} catch (Exception e) {
			logger.error(
					"invoke account findTallySerialByPage page ServiceException:",
					e);
			throw new OrderServiceException(
					OrderResponseCode.HESSIAN_INVOKE_EXCEPTION,
					"invoke account findTallySerialByPage page exception", e);
		}

		return tallySerials;
	}

	@Override
	public void transfer(Transfer transfer)
			throws OrderServiceException {
		try {
			transferService.transfer(transfer);
		} catch (AccountServiceException se) {
			logger.error("invoke account transfer ServiceException:", se);
			throw new OrderServiceException(OrderResponseCode.ORDER_RESPONSE_ACC_HANDEL_FAIL, "account service error" + se.getMessage());
		} catch (Exception e) {
			// hessian超时，但不能肯定账户记账失败 RemoteConnectFailureException ->
			// HessianConnectionException -> SocketTimeoutException
			if (null != e.getCause()
					&& null != e.getCause().getCause()
					&& e.getCause().getCause() instanceof SocketTimeoutException) {
				logger.error("invoke account transfer timeout:", e);
				throw new OrderServiceException(
						OrderResponseCode.HESSIAN_INVOKE_TIMEOUT,
						"invoke account transfer timeout", e);
			} else {
				logger.error("invoke account transfer Exception:", e);
				throw new OrderServiceException(
						OrderResponseCode.HESSIAN_INVOKE_EXCEPTION,
						"invoke account transfer Exception", e);
			}
		}
	}


	@Override
	public void transferWithoutPsw(Transfer transfer)
			throws OrderServiceException {
		try {
			transferService.transferWithoutPsw(transfer);
		} catch (AccountServiceException se) {
			logger.error("invoke account transferWithoutPsw ServiceException:",
					se);
			throw new OrderServiceException(OrderResponseCode.ORDER_RESPONSE_ACC_HANDEL_FAIL, "account service error" + se.getMessage());
		} catch (Exception e) {
			// hessian超时，但不能肯定账户记账失败 RemoteConnectFailureException ->
			// HessianConnectionException -> SocketTimeoutException
			if (null != e.getCause()
					&& null != e.getCause().getCause()
					&& e.getCause().getCause() instanceof SocketTimeoutException) {
				logger.error("invoke account transferWithoutPsw timeout:", e);
				throw new OrderServiceException(
						OrderResponseCode.HESSIAN_INVOKE_TIMEOUT,
						"invoke account transferWithoutPsw timeout:", e);
			} else {
				logger.error("invoke account transferWithoutPsw Exception:", e);
				throw new OrderServiceException(
						OrderResponseCode.HESSIAN_INVOKE_EXCEPTION,
						"invoke account transferWithoutPsw Exception:", e);
			}
		}
	}

	

	@Override
	public List<TallySerial> findTallySerial(TallySerialQuery tallySerialQuery)
			throws OrderServiceException {
		try {
			return tallySerialService.findTallySerial(tallySerialQuery);
		} catch (AccountServiceException se) {
			logger.error("invoke account findTallySerial ServiceException:", se);
			throw new OrderServiceException(OrderResponseCode.ORDER_RESPONSE_ACC_HANDEL_FAIL, "account service error" + se.getMessage());
		} catch (Exception e) {
			logger.error("invoke account findTallySerial Exception:", e);
			throw new OrderServiceException(
					OrderResponseCode.HESSIAN_INVOKE_EXCEPTION,
					"invoke account findTallySerial Exception:", e);
		}
	}

}
